package cn.lzd.mvp.base.net;

import android.net.ParseException;
import androidx.annotation.NonNull;
import cn.lzd.mvp.base.struct.IView;
import com.blankj.utilcode.util.ToastUtils;
import com.google.gson.JsonParseException;
import io.reactivex.ObservableTransformer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import org.jetbrains.annotations.NotNull;
import org.json.JSONException;
import retrofit2.HttpException;

import java.net.SocketTimeoutException;
import java.net.UnknownHostException;

public class RxUtils {

    /**
     * 应用 带弹窗的 网络请求线程
     * 同步有线程切换、生命周期绑定、以及错误异常处理
     * @param view 要绑定的线程
     * @return 转换后的Observable
     *
     * applySchedulers  有点像 组件方法
     */
    public static <T> ObservableTransformer<T, T> applySchedulers(final IView view) {
        return observable -> observable
                .subscribeOn(Schedulers.io())//增加了一个线程，就是 订阅一个IO 其实就是订阅了一个观察
                .doOnSubscribe(disposable -> {
                    // 在开始请求时做
                    view.showLoading();//显示进度条等
                })
                // 交付数据在 UI 主线程
                // 你使用时已经不用再关心了
                .observeOn(AndroidSchedulers.mainThread())
                // 在结束请求时做
                .doFinally(view::hideLoading)
                .onErrorReturn(throwable -> {
                    // 发生错误时做
                    // 如果发生了不可预支的错误呢？
                    // 还有最后一道保障
                    handleError(view, throwable);//run了一个线程用handler处理错误
                    return null;
                });
    }

    private static void handleError(final IView view, @NonNull Throwable throwable) {
        try {
            ToastUtils.cancel();
            getErrorMessageToShow(throwable, view::showMessage);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void getErrorMessageToShow(Throwable throwable, @NotNull IMessageListener messageListener) {
        String message = throwable.getMessage();
        if (message != null && message.startsWith("The exception was not handled due to missing onError handler")) {
            // do none
            return;
        }
        String msg;
        if (throwable instanceof UnknownHostException) {
            msg = "网络不可用";
        } else if (throwable instanceof SocketTimeoutException) {
            msg = "请求网络超时";
        } else if (throwable instanceof HttpException) {
            HttpException httpException = (HttpException) throwable;
            msg = convertStatusCode(httpException);
        } else if (throwable instanceof JsonParseException || throwable instanceof ParseException || throwable instanceof JSONException) {
            msg = "数据解析错误";
        } else {
            msg = "未知错误";
        }
        messageListener.onReceive(msg);
    }

    private static String convertStatusCode(HttpException httpException) {
        String msg;
        if (httpException.code() == 500) {
            msg = "服务器发生错误";
        } else if (httpException.code() == 404) {
            msg = "请求地址不存在";
        } else if (httpException.code() == 403) {
            msg = "请求被服务器拒绝";
        } else if (httpException.code() == 401) {
            msg = "未授权";
        } else if (httpException.code() == 307) {
            msg = "请求被重定向到其他页面";
        } else {
            msg = httpException.message();
        }
        return msg;
    }

    public interface IMessageListener {
        void onReceive(String msg);
    }
}
